#include "param.h"
#include "gpio.h"
#include "usart.h"
#include "w25qxx.h"
#include "string.h"
#include "bcd.h"
#include "lora.h"
#include "common.h"

uint8_t paramMode;
uint8_t paramNeedSave=0; //用于标记是否需要把参数保存进spi flash

typedef enum
{
	PUART_STATE_IDLE=0X00,
	PUART_STATE_REC_HEAD,
	PUART_STATE_REC_DATA,
	PUART_STATE_REC_END,
	PUART_STATE_REC_DEAL,
}param_uart_state;

struct
{
	uint8_t rxbuf[30];
	uint8_t rxCounter;
	uint8_t txbuf[30];
	uint8_t txCounter;
	uint8_t state;
}paramUart;

#pragma pack(1) //结构体按照1字节对齐
tSysParam nowSysParam;
const tSysParam defaultSysParam=
{
	0x55,	//0x55代表存入flash，其他值代表没存入
	0x2018,
	0xFE,	//node add
	0X00,	//radio ch
	0X05,	//baud
	0x08,	//串口数据位8位
	0X00, //无奇偶校验位
	0x02, //两位停止位
	0x05, //数据采集周期	
};
#pragma pack()

void param_init()
{
	paramNeedSave=0;
	w25q_init();
	w25q_read((uint8_t *)&nowSysParam,0x0000,sizeof(nowSysParam)); //从SPI地址0x0000处读取结构体数据
	if(nowSysParam.saveFlag!=0x55)  //证明spi flash没有存储进参数
	{
		memcpy(&nowSysParam,&defaultSysParam,sizeof(nowSysParam)); //把默认值更新到当前参数中
		w25q_eraseSector(0x0000);
		w25q_writeNoCheck((uint8_t *)&nowSysParam,0x0000,sizeof(nowSysParam));//把默认参数存入flash中
	}
	nowSysParam.radioCh=bcd_getValue(BCD_L);  //根据编码开关来配置无线信道
	
	paramMode=PARAM_MODE_485; //初始化为485可以设置参数模式
}
//在485参数配置模式对串口的初始化
void param_uartInit()
{
	huart1.Instance = USART1;
	huart1.Init.BaudRate = 9600;
	huart1.Init.WordLength = UART_WORDLENGTH_8B;

	huart1.Init.StopBits = UART_STOPBITS_2;
	huart1.Init.Parity = UART_PARITY_NONE;	
	huart1.Init.Mode = UART_MODE_TX_RX;
	huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	huart1.Init.OverSampling = UART_OVERSAMPLING_16;
	if (HAL_UART_Init(&huart1) != HAL_OK)
	{
		Error_Handler();
	}
	__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);	//打开串口接收中断
	
	paramUart.rxCounter=0;
	paramUart.state=PUART_STATE_REC_HEAD;
}
void param_uartDeInit()
{
	__HAL_UART_DISABLE_IT(&huart1,UART_IT_RXNE);	//关闭串口接收中断
}
uint8_t param_485CmdDeal(uint8_t *pcmd,uint8_t len)
{
	uint8_t checkValue=0X00;
	uint8_t err=0;
	//判断校验和是否正确
	if(com_getCheckSum(pcmd+1,len-3)!=pcmd[len-2])return 0;
	//根据命令码解析
	switch(pcmd[4])
	{
		case 0x01://获取系统参数
			if(len!=9)return 0;
			paramUart.txCounter=0;
			paramUart.txbuf[paramUart.txCounter++]=0x7E;
			paramUart.txbuf[paramUart.txCounter++]=nowSysParam.gatewayAdd>>8;
			paramUart.txbuf[paramUart.txCounter++]=nowSysParam.gatewayAdd&0xff;
			paramUart.txbuf[paramUart.txCounter++]=nowSysParam.nodeAdd;
			paramUart.txbuf[paramUart.txCounter++]=0x81;
			paramUart.txbuf[paramUart.txCounter++]=11; //长度
			paramUart.txbuf[paramUart.txCounter++]=0x00;//辅助标记
			//info
			param_get(paramUart.txbuf+paramUart.txCounter);
			paramUart.txCounter+=10;			
			paramUart.txbuf[paramUart.txCounter++]=checkValue;//累加和
			paramUart.txbuf[paramUart.txCounter++]=0x0D;//结尾符号
			HAL_UART_Transmit(&huart1,paramUart.txbuf,paramUart.txCounter,1000);
			break;
		case 0x02://设置系统参数
			if(len!=19)err=1;
			param_set(pcmd+7);   //指向信息域的网络地址
			paramUart.txCounter=0;
			paramUart.txbuf[paramUart.txCounter++]=0x7E;
			paramUart.txbuf[paramUart.txCounter++]=nowSysParam.gatewayAdd>>8;
			paramUart.txbuf[paramUart.txCounter++]=nowSysParam.gatewayAdd&0xff;
			paramUart.txbuf[paramUart.txCounter++]=nowSysParam.nodeAdd;
			paramUart.txbuf[paramUart.txCounter++]=0x82;
			paramUart.txbuf[paramUart.txCounter++]=0x02;//长度
			paramUart.txbuf[paramUart.txCounter++]=0x00;//辅助标记
			paramUart.txbuf[paramUart.txCounter++]=err;//正常返回
			paramUart.txbuf[paramUart.txCounter++]=checkValue;//累加和
			paramUart.txbuf[paramUart.txCounter++]=0x0D;//结尾符号
			HAL_UART_Transmit(&huart1,paramUart.txbuf,paramUart.txCounter,1000);
			break;
	}
	
	return 1;
}

uint8_t param_485modePoll()
{
	uint8_t pollState=0;
	uint16_t timer=0;
	while(1)
	{
		switch(pollState)
		{
			case 0:				//进入485设置参数之前初始化状态
				LEDP_ON();
				LEDD_OFF();
				param_uartInit();
				pollState=1;
				break;
			case 1:			//进入485设置参数状态
				timer++;
				if(timer%100==0)
				{
					LEDD_TOGGLE();
					LEDP_TOGGLE();		
				}
				if(timer>=5000) //超时退出
				{
					timer=0;
					pollState=2;
				}
				if(paramUart.state==PUART_STATE_REC_DEAL)
				{
					timer=0;
					//HAL_UART_Transmit(&huart1,paramUart.rxbuf,paramUart.rxCounter,1000);
					param_485CmdDeal(paramUart.rxbuf,paramUart.rxCounter);
					paramUart.state=PUART_STATE_REC_HEAD;
					paramUart.rxCounter=0;			
				}				
				break;
			case 2:					//退出485设置系统参数状态				
				paramUart.state=PUART_STATE_IDLE;
				paramMode=PARAM_MODE_LORA;
				LEDP_ON();
				LEDD_OFF();
				param_uartDeInit();
				return 0;				
		}
		HAL_Delay(1);		
	}
}
uint8_t param_getMode()
{
	return paramMode;
}
//传入的参数从网络地址开始
void param_set(uint8_t *pbuf)
{
	if(paramNeedSave==1)return;   //之前的参数还没有保存，操作过快
	nowSysParam.gatewayAdd=(pbuf[0]<<8)+pbuf[1];
	nowSysParam.nodeAdd=pbuf[2];
	nowSysParam.radioCh=pbuf[3];
	nowSysParam.baud=pbuf[4];
	nowSysParam.dataBit=pbuf[5];
	nowSysParam.checkBit=pbuf[6];
	nowSysParam.stopBit=pbuf[7];
	nowSysParam.dataInterval=(pbuf[8]<<8)+pbuf[9];
	if(paramMode==PARAM_MODE_485)  //串口更新时直接写入spi flash中
	{
		w25q_eraseSector(0x0000);
		w25q_writeNoCheck((uint8_t *)&nowSysParam,0x0000,sizeof(nowSysParam));//把默认参数存入flash中		
	}
	else	paramNeedSave=1;
}

void param_get(uint8_t *pbuf)
{
		pbuf[0]=nowSysParam.gatewayAdd>>8;
		pbuf[1]=nowSysParam.gatewayAdd&0xff;
		pbuf[2]=nowSysParam.nodeAdd;
		pbuf[3]=nowSysParam.radioCh;
		pbuf[4]=nowSysParam.baud;
		pbuf[5]=nowSysParam.dataBit;
		pbuf[6]=nowSysParam.checkBit;
		pbuf[7]=nowSysParam.stopBit;
		pbuf[8]=nowSysParam.dataInterval>>8;
		pbuf[9]=nowSysParam.dataInterval&0xff;	 
}
uint16_t param_get_gatewayAdd()
{
	return nowSysParam.gatewayAdd;
}
uint8_t param_get_nodeAdd()
{
	return nowSysParam.nodeAdd;
}
void param_set_radioCh(uint8_t ch)
{
	nowSysParam.radioCh=ch;
	if(paramMode==PARAM_MODE_485)  //串口更新时直接写入spi flash中
	{
		w25q_eraseSector(0x0000);
		w25q_writeNoCheck((uint8_t *)&nowSysParam,0x0000,sizeof(nowSysParam));//把默认参数存入flash中		
	}
	else	paramNeedSave=1;		
}
uint8_t param_get_radioCh()
{
	return nowSysParam.radioCh;
}
uint8_t param_get_baud()
{
	return nowSysParam.baud;
}
uint8_t param_get_dataBit()
{
	return nowSysParam.dataBit;
}
uint8_t param_get_checkBit()
{
	return nowSysParam.checkBit;
}
uint8_t param_get_stopBit()
{
	return nowSysParam.stopBit;
}
uint16_t param_get_dataInterval()
{
	return nowSysParam.dataInterval;
}

void param_uartIrq()
{
	uint8_t ch;
	HAL_NVIC_ClearPendingIRQ(USART1_IRQn);
	if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE)!=RESET))
	{
		__HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE);
		ch=(uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF);
	}
	switch(paramUart.state)
	{
		case PUART_STATE_REC_HEAD:
			paramUart.state=0;
			if(ch==0x7e)
			{
				paramUart.rxbuf[paramUart.rxCounter++]=ch;
				paramUart.state=PUART_STATE_REC_DATA;
				
			}
			break;
		case PUART_STATE_REC_DATA:
			paramUart.rxbuf[paramUart.rxCounter++]=ch;
			if(paramUart.rxCounter==(7+paramUart.rxbuf[5]))
			{
				paramUart.state=PUART_STATE_REC_END;
			}
			break;
		case PUART_STATE_REC_END:
			if(ch==0x0D)
			{
				paramUart.rxbuf[paramUart.rxCounter++]=ch;
				paramUart.state=PUART_STATE_REC_DEAL;
			}
			else
			{
				paramUart.state=PUART_STATE_REC_HEAD;
			}
			break;
	}
}
void ParamTask(void const * argument)
{
	uint8_t tch;
  for(;;)
  {
		tch=bcd_getValue(BCD_L);
		if(tch!=nowSysParam.radioCh)
		{
			param_set_radioCh(tch);
			lora_chChange();
			//D1_TOGGLE();
		}
		
		if(paramNeedSave==1)   //参数有更新，需要存入spi flash中
		{
			w25q_eraseSector(0x0000);
			w25q_writeNoCheck((uint8_t *)&nowSysParam,0x0000,sizeof(nowSysParam));//把默认参数存入flash中
			paramNeedSave=0;
		}
//		if(nowSysParam.saveFlag==0X55)
//		{
//			D1_TOGGLE();
//		}
    osDelay(10);
  }
}
